package com.cskaoyan.javase.object._2tostring;

/**
 * toString方法
 * 1.方法的声明:
 *      public String toString()
 *      是一个随便访问,无参的方法
 *      需要注意它有返回值,返回一个字符串
 *
 * 2.方法的作用:
 *      1.返回该对象（调用toString方法的对象）的字符串表示。
 *      2.通常，toString方法会返回一个“以文本方式表示”此对象的字符串。
 *      3.结果应是一个简明但易于读懂的信息表达式。
 *      以上都是在说,这个方法将对象转换成一个简明的字符串
 *          说白了,这个字符串就是为了描述该对象的
 *      4.建议所有子类都重写此方法。
 *
 *
 * 3.Object类当中的默认实现:
 *      return getClass().getName() + "@" + Integer.toHexString(hashCode());
 *      解释:
 *          首先获取类的运行时Class对象,调用getName方法
 *          获取类的全限定类名
 *          Integer.toHexString(int) 该方法将一个int十进制整数,转换成十六进制字符串
 *          hashCode()是Object类当中的方法,默认情况下(不重写它的情况下)
 *              该方法是通过计算对象的地址,得到一个十进制整数
 *              所以hashCode()的返回值,可以近似看成对象地址的十进制整数表示
 *          Integer.toHexString(hashCode()) 整体是获取对象的地址的十六进制表示
 *
 *          总之,默认实现是打印:
 *              类的全限定类名 + "@" + 对象的十六进制地址值
 *
 * 实际上,在Java代码中,如果直接输出引用(对象名)或者
 * 使用引用参与拼接字符串"+"运算,都会隐式调用该类的toString方法
 * 如果该类没有重写toString方法,那就调用Object类的默认实现,打印对象的地址值.
 *
 * 4.在很多情况下,地址值我们不想看,描述对象,查看对象信息,往往是需要查看对象的属性取值
 *      所以需要在子类中重写toString方法
 *      重写toString方法没有固定格式,根据需要打印属性取值即可.
 *
 *      当然实际开发 中,没有必要手写toString方法(除非特殊需求)
 *      可以直接用alt + insert快速重写
 *
 * 注意事项:
 *      1.toString方法的作用在绝大多数情况下,都是为了打印属性的取值的
 *          不要在toString方法中,写业务代码,获取其他的不相关代码
 *          建议不要手写toString方法,而是快捷键自动生成它.
 *
 *          重写toString方法,乱加代码
 *          比如赋值,有时是会引起错误的.
 *          Debug模式下,idea运行创建对象的语句时,
 *          会自动调用该类的toString方法方法,打印对象信息
 *
 *
 *      2.如果类中有引用数据类型成员变量
 *          就继续拼接这个引用数据类型成员变量即可
 *          如果是String,就直接拼字符串
 *          如果是其他引用数据类型,需要拼该类的toString方法结果,
 *          所以该类也需要重写toString方法
 *
 *
 *      3.直接打印引用或者使用引用拼接字符串,会隐式调用toString方法
 *          需要写出来吗?
 *          或者说写不写都行呢?
 *
 *          不要写出来,不要画蛇添足
 *          避免出现空指针异常
 *
 *
 * @since 11:42
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        /*Student s1 = new Student(18, 750);
        System.out.println(s1);
        System.out.println(s1 + "666");
        Student s2 = new Student(18, 750);
        System.out.println(s2);

        System.out.println(s1.age);
        System.out.println(s2.age);*/

        Student s = new Student(18, 100);
        System.out.println(s.age);


        Student s2 = new Student(18, 100, "张三", new Star(10000));
        System.out.println(s2);

        Student s3 = new Student(19, 80, "李四", null);
        System.out.println(s3);
    }
}

class Student {
    int age;
    double score;
    String name;
    Star s;

    public Student() {
    }

    public Student(int age, double score) {
        this.age = age;
        this.score = score;
    }

    public Student(int age, double score, String name, Star s) {
        this.age = age;
        this.score = score;
        this.name = name;
        this.s = s;
    }
    /*@Override
    public String toString() {
        return "Student{ age = " + age + ", score = " + score + " }";
    }*/

    /*@Override
    public String toString() {
        // age = 100;
        return "Student{" +
                "age=" + age +
                ", score=" + score +
                '}';
    }*/

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", score=" + score +
                ", name='" + name + '\'' +
                ", s=" + s +
                '}';
    }
}

class Star {
    double salary;

    public Star(double salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Star{" +
                "salary=" + salary +
                '}';
    }
}